#include "StdAfx.h"
#include "e_voting.h"
#include <algorithm>
#include <time.h>
#include <stdlib.h>
#include <iostream>

using std::generate;
using std::for_each;
using std::cout;


e_voting::e_voting(vector<string> questions, size_t participants, size_t sets)
	//:_q(questions.size())
{
	cout<< string(40, '-')<<"\n";
	printf("\t The E-voting protocol.\n\n");
	printf("Number of voters: %i\n", participants);
	printf("Number of sets of messages: %i\n", sets);
	
	size_t i = 0;
	printf("Questionnaire: \n");
	for_each(questions.begin(), questions.end(), [&](string question){
		
		printf("\t %i. %s.\n", ++i, question.c_str());

	});
	cout<< string(40, '-')<<"\n";

	_tallier = new tallier(questions);
	_voters.resize(participants);

	size_t _q = questions.size();
	
	i = 0;
	generate(_voters.begin(), _voters.end(), [&]() -> voter*
	{
		printf("\t The %i-th voter:\n", ++i);
		return new voter(_tallier,_q,sets);
	});
}


e_voting::~e_voting()
{
	if(_tallier != NULL) delete _tallier;
	for_each(_voters.begin(), _voters.end(), [&](voter* v)
	{
		if(v != NULL) delete v;
	});
}

void e_voting::start()
{
	srand(unsigned(time(NULL)));

	printf("\n\t Start the E-voting!\n");

	for_each(_voters.begin(), _voters.end(), [&](voter* v)
	{
		// A -> T : B1,...,Bk 
		printf("\nA -> T : B1,...,Bk \n");
		const messages blmsgs = v->get_blinded_messages();

		// T -> A : j
		printf("\nT -> A : j \n");
		const size_t j = rand() % blmsgs.size();
		
		printf("j = %i\n", j);
		
		// A -> T : F1, ..., Fj-1,Fj+1,...,Fk
		printf("\nA -> T : F1, ..., Fj-1,Fj+1,...,Fk \n");
		const keys unblks = v->get_unblinded_keys(j);

		// B1, ..., Bj-1,Bj+1,...,Bk
		messages msgstounblnd = blmsgs;
		msgstounblnd.erase(msgstounblnd.begin() + j);
		
		// T : plain messages
		printf("\nT : plain messages \n");
		_tallier->get_plain_messages(msgstounblnd, unblks);

		// T -> A : Bj = Q1,...,Qs 
		printf("\nT -> A : Bj = Q1,...,Qs \n");
		const messages_set sgndblndmsgs = _tallier->get_blind_signed_messages_set(blmsgs[j]);

		// A : S1,...Ss
		printf("\nA : S1,...Ss \n");
		const messages_set sgndmsgs =v->get_signed_messages_set(sgndblndmsgs);

		// A : make the choice
		printf("\nA : make the choice \n");
		signed_message sgndmsg = v->make_choice();

		// T : check and take or drop the vote
		printf("\nT : check and take or drop the vote \n");
		bool check = _tallier->check_vote(sgndmsg);

	});


	vector<unsigned int> elections_res = _tallier->get_results();
	questionnarie questions = _tallier->get_questionnaire();
	
	cout<<string(40, '-') <<"\n";
	printf("Number of votes:\n");

	for(size_t i = 0; i< elections_res.size(); ++i)
	{
		printf("%i. %s : %i votes.\n", i+1, questions[i].c_str(), elections_res[i]);
	}
}
